from paho.mqtt import client as mqtt_client
import threading
from typing import Dict, Callable, Any, Optional, List
from common.utils.log_util import logger

class MQTTClientManager:
    def __init__(self):
        self.clients: Dict[str, mqtt_client.Client] = {}
        self.callbacks: Dict[str, List[Callable]] = {}  # 用于存储每个客户端的消息回调列表
        self.is_create: bool = True

    def create_client(
            self,
            client_id: str,
            broker: str,
            port: int = 1883,
            username: str = None,
            password: str = None,
            on_connect_callback: Callable = None,
            on_message_callback: Callable = None,
            on_disconnect_callback: Callable = None
    ) -> mqtt_client.Client:
        """创建并连接一个 MQTT 客户端"""
        def on_connect(client, userdata, flags, rc):
            """连接回调"""
            if rc == 0:
                logger.info("mqtt链接成功")
            elif rc == 4:
                error_msg = "连接被拒绝-用户名或密码错误"
                logger.error(error_msg)
                raise ConnectionError(error_msg)
            elif rc == 5:
                error_msg = "连接被拒绝-未授权"
                logger.error(error_msg)
                raise ConnectionError(error_msg)
            else:
                error_msg = f"连接失败，返回代码{rc}"
                logger.error(error_msg)
                raise ConnectionError(error_msg)

        def on_message(client, userdata, message):
            """消息回调"""
            try:
                # 执行所有自定义回调
                for callback in self.callbacks.get(client_id, []):
                    callback(client, userdata, message)
            except Exception as e:
                logger.error(f"Error processing message: {str(e)}")
                logger.debug(f"Error details: {e}", exc_info=True)

        def on_disconnect(client, userdata, rc):
            """断开连接回调"""
            if rc != 0:
                logger.warning(f"Unexpected disconnection (rc={rc})")

        client = mqtt_client.Client(client_id=client_id)
        client.on_connect = on_connect_callback if on_connect_callback else on_connect
        client.on_message = on_message
        client.on_disconnect = on_disconnect_callback if on_disconnect_callback else on_disconnect

        # 设置账号和密码
        if username and password:
            client.username_pw_set(username, password)

        # 启动同步连接（需在独立线程运行）
        def connect():
            client.connect(broker, port)
            client.loop_start()

        thread = threading.Thread(target=connect)
        thread.start()
        thread.join(timeout=5)  # 等待连接完成

        self.clients[client_id] = client
        self.callbacks[client_id] = []  # 初始化回调列表
        return client

    def add_callback(self, client_id: str, on_message_callback: Callable):
        """添加客户端的消息回调函数"""
        if client_id not in self.clients:
            raise KeyError(f"客户端 {client_id} 不存在")
        self.callbacks[client_id].append(on_message_callback)

    def remove_callback(self, client_id: str, on_message_callback: Callable):
        """移除客户端的消息回调函数"""
        if client_id not in self.clients:
            raise KeyError(f"客户端 {client_id} 不存在")
        if on_message_callback in self.callbacks[client_id]:
            self.callbacks[client_id].remove(on_message_callback)
        else:
            raise ValueError(f"回调函数 {on_message_callback} 不存在于客户端 {client_id} 的回调列表中")

    def get_client(self, client_id: str) -> mqtt_client.Client:
        """获取已存在的客户端"""
        if client_id not in self.clients:
            raise KeyError(f"客户端 {client_id} 不存在")
        return self.clients[client_id]

    def close_all(self):
        """关闭所有客户端"""
        for client_id, client in self.clients.items():
            client.loop_stop()
            client.disconnect()
            print(f"客户端 {client_id} 已断开")

    def is_empty(self):
        """检查是否有客户端"""
        return len(self.clients) == 0
